package com.xiaobai.waitAndNodify;

import com.xiaobai.util.ThreadUtil;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;

/*
这个是guardedSuspension升级版 就是他的抽象版
同步模式之保护性暂停
一些RPC的框架就是用这个的
 */
public class GuardedSuspensionUpgrade {
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            People people = new People();
            people.setName("People" + i);
            people.start();
        }
        ThreadUtil.sleep(1);
        // 复制一份键集合，遍历副本（适用于集合元素不频繁变化的场景）
        Set<Integer> keys = new HashSet<>(mallBox.getKeys());
        for (Integer key : keys) {
            new PostMan(key, "内容" + key).start();
        }
    }
}
/*
用户
 */
@Slf4j
class People extends Thread{

    @Override
    public void run() {
        GuardedObjectUpgrade guardedObjectUpgrade = mallBox.createGuardedObjectUpgrade();
        log.debug("用户开始收信id为{}",guardedObjectUpgrade.getId());
        Object result = guardedObjectUpgrade.getResult(5000);
        log.debug("用户收到信id为{},内容为:{}",guardedObjectUpgrade.getId(),result);
    }
}
/*
邮递员
 */
@Slf4j
class PostMan extends Thread{
    private Integer id;
    private String msg;
    public PostMan(Integer id, String msg) {
        this.id = id;
        this.msg = msg;
    }
    @Override
    public void run() {
        GuardedObjectUpgrade guardedObjectUpgrade = mallBox.getGuardedObjectUpgrade(id);
        log.debug("邮递员发送给id为{},内容为{}",id,msg);
        guardedObjectUpgrade.setResult(msg);

    }
}
class mallBox {
    private static final Map<Integer, GuardedObjectUpgrade> guardedObjectUpgradeMap = new Hashtable<>();
    private static Integer id = 1;

    public static synchronized Integer getRandomId() {
        return id++;
    }

    public static GuardedObjectUpgrade createGuardedObjectUpgrade() {
        GuardedObjectUpgrade guardedObjectUpgrade = new GuardedObjectUpgrade(getRandomId());
        guardedObjectUpgradeMap.put(guardedObjectUpgrade.getId(), guardedObjectUpgrade);
        return guardedObjectUpgrade;
    }

    public static GuardedObjectUpgrade getGuardedObjectUpgrade(Integer id) {
        return guardedObjectUpgradeMap.remove(id);
    }
    public static Set<Integer> getKeys() {
        return guardedObjectUpgradeMap.keySet();
    }
}

@Slf4j
class GuardedObjectUpgrade {
    private Object result;
    @Getter
    private Integer id;

    public GuardedObjectUpgrade(Integer id) {
        this.id = id;
    }

    //  获取结果
    public Object getResult(long timeout) {
        synchronized (this) {
            long start = System.currentTimeMillis();
            long  wait = 0;
            while (result == null) {
               long waitTime = timeout - wait;
                if (waitTime <= 0) {
                    log.debug("超时等待....");
                    break;
                }
                try {
                    this.wait(waitTime);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                wait = System.currentTimeMillis() - start;
            }
        }
        return result;
    }

    //设置结果
    public synchronized void setResult(Object result) {
        this.result = result;
        this.notifyAll();
    }
}
